package com.legsem.jhosync.face;

import java.util.Map;

import com.legsem.jhosync.Context;

/**
 * Developers extends this class providing implementations of CRUD operations
 * against backend systems.
 * 
 */
public abstract class SourceAdapter {

    /*
     * ------------------------------------------------------------------------
     * abstract methods
     * ------------------------------------------------------------------------
     */
    /**
     * Opportunity to sign in to the backend system.
     * 
     * @param context session and configuration parameters
     * 
     * @throws SourceAdapterException if login fails
     */
    public abstract void login(Context context) throws SourceAdapterException;

    /**
     * Query the backend system and return results.
     * <p/>
     * Results are assumed to be records from a database system. Each record is
     * a Map where entries correspond to record columns.
     * <p/>
     * In turn, records are mapped to their primary key (actually to a string
     * serialization of that key).
     * <p/>
     * For example, results could look like this:
     * <p/>
     * <code>
     * { "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
     * "2"=>{"name"=>"Best", "industry"=>"Software"} }
     * </code>
     * <p/>
     * 
     * Where "1" and "2" are the primary key values corresponding to the records
     * in the backend database.
     * 
     * @param params the query parameters
     * @return a map with one entry from each record returned from the backend.
     *         A record is also a map.
     * @throws SourceAdapterException
     */
    public abstract Map < String, Map < String, Object > > query(
            Map < String, Object > params) throws SourceAdapterException;

    /**
     * Create a new entity in the backend system and return its primary key.
     * <p/>
     * Returning the primary key is very important as the client is expecting to
     * receive it before it can commit the new entity creation. In the
     * meanwhile, it is keeping a temporary entity.
     * <p/>
     * If you want to signal that creation could not be achieved, return null so
     * that the client be able to remove the temporary entity
     * 
     * @param attributes the new object attributes names and values
     * @return the created entity identifier, or primary key, as a String
     * @throws SourceAdapterException if creation fails
     */
    public abstract String create(Map < String, Object > attributes)
            throws SourceAdapterException;

    /**
     * Update an entity with new values.
     * <p/>
     * The attributes will have an additional id that points to the primary key
     * of the entity to be updated. Otherwise only the modified attributes will
     * be there.
     * 
     * @param attributes the attributes names and values which have changed
     * @throws SourceAdapterException if update fails
     */
    public abstract void update(Map < String, Object > attributes)
            throws SourceAdapterException;

    /**
     * Remove an entity from the backend.
     * <p/>
     * The attributes will have an additional id that points to the primary key
     * of the entity to be deleted.
     * 
     * @param attributes all the entity attributes
     * @throws SourceAdapterException if delete fails
     */
    public abstract void delete(Map < String, Object > attributes)
            throws SourceAdapterException;

    /**
     * Signoff from the backend system.
     * 
     * @throws SourceAdapterException if signing off fails
     */
    public abstract void logoff() throws SourceAdapterException;

    /*
     * ------------------------------------------------------------------------
     * default implementations
     * ------------------------------------------------------------------------
     */

    /**
     * Override this method if you wish to send UI metadata to the mobile
     * device.
     * 
     * @return the metadata as a CLOB
     */
    public String metadata() {
        return null;
    }
}
